package group2assignone.func;

import group2assignone.dao.MyDAO;
import group2assignone.model.Administrator;
import group2assignone.model.Customer;
import group2assignone.model.Flight;
import group2assignone.model.Manager;
import group2assignone.ucm.UCStartup;
import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;

/**
 * Class for authenticating user logins and field details for
 * managers, customers and flights.
 * @author group2
 */
public class Authentication {

    private String errorMsg;
    private boolean ok;
    private static final int usernameMin = 6;
    private static final int usernameMax = 20;
    private static final int passwordLength = 8;
    private static final int dobLength = 10;
    private MyDAO coms = UCStartup.getInstance().getDAO();

    /**
     * Checks the fields entered by the user are
     * non null and valid.
     * @param newCust
     * @return true if fields are valid
     */
    public boolean checkCustFields(Customer newCust) {
        errorMsg = new String();
        String username = newCust.getUsername();
        String password = newCust.getPassword();
        String fName = newCust.getFName();
        String lName = newCust.getLName();
        String dob = newCust.getDob();

        if (username.isEmpty()) {
            errorMsg = "Username Cannot Be Blank";
            return false;
        } else if (password.isEmpty()) {
            errorMsg = "Password Cannot Be Blank";
            return false;
        } else if (fName.isEmpty()) {
            errorMsg = "First Name Cannot Be Blank";
            return false;
        } else if (lName.isEmpty()) {
            errorMsg = "Last Name Cannot Be Blank";
            return false;
        } else if (dob.isEmpty()) {
            errorMsg = "Date of Birth Cannot Be Blank";
            return false;
        } else if ((username.length() < usernameMin) || (username.length() > usernameMax)) {
            errorMsg = "Username must be between " + usernameMin + "and " + usernameMax + " characters long";
            return false;
        } else if (!(password.length() == passwordLength)) {
            errorMsg = "Password must be " + passwordLength + " characters long";
        } else if (!(checkDOB(dob))) {
            errorMsg = "Invalid Date";
            return false;
        }
        return true;
    }

    private boolean checkDOB(String dob) {
        char[] dobChars = dob.toCharArray();
        if (!(dob.length() == dobLength)) {
            return false;
        }
        return true;
    }

    /**
     * Checks the fields are valid for creating or editing a manager.
     * @param newMan
     * @return true if fields are valid
     */
    public boolean checkManagerFields(Manager newMan) {
        errorMsg = new String();
        String username = newMan.getUsername();
        String password = newMan.getPassword();
        String fName = newMan.getFName();
        String lName = newMan.getLName();
        String dob = newMan.getDob();

        if (username.isEmpty()) {
            errorMsg = "Username Cannot Be Blank";
            return false;
        } else if (password.isEmpty()) {
            errorMsg = "Password Cannot Be Blank";
            return false;
        } else if (fName.isEmpty()) {
            errorMsg = "First Name Cannot Be Blank";
            return false;
        } else if (lName.isEmpty()) {
            errorMsg = "Last Name Cannot Be Blank";
            return false;
        } else if (dob.isEmpty()) {
            errorMsg = "Date of Birth Cannot Be Blank";
            return false;
        } else if ((username.length() < usernameMin) || (username.length() > usernameMax)) {
            errorMsg = "Username must be between " + usernameMin + "and " + usernameMax + " characters long";
            return false;
        } else if (!(password.length() == passwordLength)) {
            errorMsg = "Password must be " + passwordLength + " characters long";
        } else if (!(checkDOB(dob))) {
            errorMsg = "Invalid Date";
            return false;
        }
        return true;
    }

    /**
     * Checks the fields are valid for searching for a flight.
     * Departure and Arrival locations must be different, date must be valid.
     * @param flight
     * @return true if fields are valid
     */
    public boolean checkFlightFields(Flight flight) {
        if (flight.getDepLoc().equals(flight.getArrLoc())) {
            errorMsg = "Arrival and Departure locations cannot be the same";
            return false;
        }

        return true;
    }

    /**
     * Authenticates login details for customer by
     * checking if details exist in the database.
     * @param user
     * @return true if customer is part of the database
     */
    public boolean authCustomer(Customer user) {
        if (coms.sQLCustomerExists(user)) {
            return true;
        } else {
            errorMsg = "This customer account does not exist";
            return false;
        }
    }

    /**
     * Authenticates login details for manager by
     * checking if details exist in the database.
     * @param user
     * @return true if manager is part of the database
     */
    public boolean authManager(Manager user) {
        if (coms.sQLManagerExists(user)) {
            return true;
        } else {
            errorMsg = "This manager account does not exist";
            return false;
        }
    }

    /**
     * Uses LDAP JCU to authenticate login details
     * code downloaded and personalised from:
     * http://www.andrewnoske.com/student/downloads/jcu/ldaptest.java
     * @param user
     * @return true if login details match a JCU member
     */
    public boolean authAdmin(Administrator user) {

        String username = user.getUsername();
        String password = user.getPassword();
        Hashtable env = new Hashtable();
        errorMsg = new String("Invalid Username or Password");

        if (user.getUsername().isEmpty()) {
            errorMsg = "Username Cannot Be Blank";
            return false;
        } else if (user.getPassword().isEmpty()) {
            errorMsg = "Password Cannot Be Blank";
            return false;
        } else {
            env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
            env.put(Context.PROVIDER_URL, "ldap://ldap.jcu.edu.au:389/dc=jcu,dc=edu,dc=au");
            env.put(Context.SECURITY_AUTHENTICATION, "simple");
            env.put(Context.SECURITY_PRINCIPAL, "uid=" + username + ",ou=Users,dc=jcu,dc=edu,dc=au");
            env.put(Context.SECURITY_CREDENTIALS, password);

            try {
                DirContext ctx;
                ctx = new InitialDirContext(env);

                ok = true;
            } catch (javax.naming.AuthenticationException e) {
            } catch (javax.naming.NamingException e) {
            }
            return ok;
        }

    }

    /**
     * Returns the errorMsg set by an authentication process.
     * @return String errorMsg
     */
    public String getErrorMsg() {
        return errorMsg;
    }
}
